package top.abilities.util.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import top.abilities.util.db.DataSourceEnum;
import top.abilities.util.db.DynamicDataSource;
import top.abilities.util.util.AESUtil;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

//@Configuration
//@MapperScan({"top.abilities.admin.moudle.fes.dao.mapper"})
public class MybatisConfig {

    @Autowired
    private Environment env;

    @Bean
    public DataSource masterDataSource() throws Exception{
        Properties props=new Properties();
        props.put("driverClassName", env.getProperty("master.spring.datasource.driverClassName"));
        props.put("url", env.getProperty("master.spring.datasource.url"));
        props.put("username", env.getProperty("master.spring.datasource.username"));
        props.put("password", AESUtil.AESDecode(env.getProperty("master.spring.datasource.password")));
//        props.put("initialSize",1);
//        props.put("minIdle",1);
//        props.put("maxActive",50);
//        props.put("maxWait",60000);
//        props.put("timeBetweenEvictionRunsMillis",60000);
//        props.put("minEvictableIdleTimeMillis",300000);
//        props.put("validationQuery","SELECT 1");
//        props.put("testWhileIdle",true);
//        props.put("testOnBorrow",false);
//        props.put("testOnReturn",false);
//        props.put("filters","stat");
//        DruidDataSourceFactory.createDataSource(props);
        DruidDataSource datasource = new DruidDataSource();
        datasource.setUrl(env.getProperty("master.spring.datasource.url"));
        datasource.setDriverClassName(env.getProperty("master.spring.datasource.driverClassName"));
        datasource.setUsername(env.getProperty("master.spring.datasource.username"));
        datasource.setPassword(AESUtil.AESDecode(env.getProperty("master.spring.datasource.password")));
        datasource.setInitialSize(5);
        datasource.setMaxActive(500);
        datasource.setMinIdle(1);
        datasource.setMaxWait(60000);
        datasource.setMinEvictableIdleTimeMillis(300000);
        datasource.setValidationQuery("SELECT 1");
        datasource.setTestWhileIdle(true);
        datasource.setTestOnBorrow(false);
        datasource.setTestOnReturn(false);
        datasource.setFilters("stat");
        datasource.setTimeBetweenConnectErrorMillis(60000);
        return datasource;
    }

    @Bean
    public DataSource slaveDataSource() throws Exception{
        Properties props=new Properties();
        props.put("driverClassName", env.getProperty("slave.spring.datasource.driverClassName"));
        props.put("url", env.getProperty("slave.spring.datasource.url"));
        props.put("username", env.getProperty("slave.spring.datasource.username"));
        props.put("password", AESUtil.AESDecode(env.getProperty("slave.spring.datasource.password")));
//        props.put("initialSize",1);
//        props.put("maxActive",50);
//        props.put("maxWait",60000);
//        props.put("minIdle",1);
//        props.put("minEvictableIdleTimeMillis",300000);
        props.put("validationQuery","SELECT 1");
//        props.put("testWhileIdle",true);
//        props.put("testOnBorrow",false);
//        props.put("testOnReturn",false);
//        props.put("filters","stat");
//        props.put("timeBetweenEvictionRunsMillis",60000);
//        DataSource source = DruidDataSourceFactory.createDataSource(props);
        DruidDataSource datasource = new DruidDataSource();
        datasource.setDriverClassName(env.getProperty("slave.spring.datasource.driverClassName"));
        datasource.setUrl(env.getProperty("slave.spring.datasource.url"));
        datasource.setUsername(env.getProperty("slave.spring.datasource.username"));
        datasource.setPassword(AESUtil.AESDecode(env.getProperty("slave.spring.datasource.password")));
        datasource.setInitialSize(5);
        datasource.setMaxActive(500);
        datasource.setMaxWait(60000);
        datasource.setMinIdle(1);
        datasource.setMinEvictableIdleTimeMillis(300000);
        datasource.setValidationQuery("SELECT 1");
        datasource.setTestWhileIdle(true);
        datasource.setTestOnReturn(false);
        datasource.setTestOnBorrow(false);
        datasource.setFilters("stat");
        datasource.setTimeBetweenConnectErrorMillis(60000);
        return datasource;
    }

    /**
     *
     * @param masterDataSource
     * @param slaveDataSource
     * @Primary 该注解表示在同一个接口有多个实现类可以注入的时候，默认选择哪一个，而不是让@autowire注解报错
     * @Qualifier 根据名称进行注入，通常是在具有相同的多个类型的实例的一个注入（例如有多个DataSource类型的实例）
     * @return
     */
    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource){
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceEnum.MASTER.getName(),masterDataSource);
        targetDataSources.put(DataSourceEnum.SLAVE.getName(),slaveDataSource);

        DynamicDataSource dataSource=new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(masterDataSource);
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource,
                                               @Qualifier("slaveDataSource")DataSource slaveDataSource) throws Exception{
        SqlSessionFactoryBean sfb=new SqlSessionFactoryBean();
        // 指定数据源(这个必须有，否则报错)
        sfb.setDataSource(this.dataSource(masterDataSource,slaveDataSource));
       // sfb.setConfigLocation("classpath:mybatis-config.xml");
        sfb.setConfigLocation(new DefaultResourceLoader().getResource("classpath:mybatis-config.xml"));
        return sfb.getObject();
    }

    @Bean
    public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception{
        return new DataSourceTransactionManager(dataSource);
    }
}
